package com.webex.ta.hydra.gui.action;

import com.webex.ta.hydra.util.ClassFinder;
import com.webex.ta.hydra.util.HydraUtils;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Modifier;
import java.util.*;
import java.io.File;

/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-8-20
 * Time: 9:26:00
 */
public class ActionRouter implements ActionListener {
    private Map<String, Set<ActionHandler>> commands = new HashMap<String, Set<ActionHandler>>();

    private static ActionRouter router;

    private ActionRouter() {
    }

    public static ActionRouter getInstance() {
        if (router == null) {
            router = new ActionRouter();
            router.populateCoreCommandMap();
        }
        return router;
    }

    public void populatePluginCommandMap(String pluginName) {
//        HydraUtils.getHydraPluginPath()
        String[] path = new String[1];
        path[0] = HydraUtils.getHydraPluginPath() + File.separator + pluginName;
        populateCommandMap(path);
    }

    public void populateCommandMap(File dir) {
        String[] path = new String[1];
        path[0] = dir.getAbsolutePath();
        populateCommandMap(path);
    }

    private void populateCommandMap(String[] paths) {
        Class actionClass;

        try {
            List<String> listClasses = ClassFinder.findClassesThatExtend(paths, new Class[]{Class
                    .forName("com.webex.ta.hydra.gui.action.ActionHandler")});

            for (String actionClassName : listClasses) {
                actionClass = Class.forName(actionClassName);
                if (!Modifier.isAbstract(actionClass.getModifiers())) {
                    ActionHandler action = (ActionHandler) actionClass.newInstance();
                    for (String actionName : action.getActionNames()) {
                        Set<ActionHandler> actionObjects = commands.get(actionName);
                        if (actionObjects == null) {
                            actionObjects = new HashSet<ActionHandler>();
                            commands.put(actionName, actionObjects);
                        }

                        boolean alreadyAdded = false;
                        for (ActionHandler ah : actionObjects) {
                            if (actionClass.isAssignableFrom(ah.getClass())) {
                                alreadyAdded = true;
                                break;
                            }

                        }
                        if (!alreadyAdded)
                            actionObjects.add(action);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void populateCoreCommandMap() {
        populateCommandMap(HydraUtils.getCorePaths());
//        Class actionClass;
//
//        try {
//            List<String> listClasses = ClassFinder.findClassesThatExtend(HydraUtils.getCorePaths(), new Class[]{Class
//                    .forName("com.webex.ta.hydra.gui.action.ActionHandler")});
//
//            commands = new HashMap<String, Set<ActionHandler>>(listClasses.size());
//            for (String actionClassName : listClasses) {
//                actionClass = Class.forName(actionClassName);
//                if (!Modifier.isAbstract(actionClass.getModifiers())) {
//                    ActionHandler action = (ActionHandler) actionClass.newInstance();
//                    for (String actionName : action.getActionNames()) {
//                        Set<ActionHandler> actionObjects = commands.get(actionName);
//                        if (actionObjects == null) {
//                            actionObjects = new HashSet<ActionHandler>();
//                            commands.put(actionName, actionObjects);
//                        }
//                        actionObjects.add(action);
//                    }
//                }
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    public void doActionNow(ActionEvent e) {
		performAction(e);
	}

    private void performAction(final ActionEvent e) {
        String actionCommand = e.getActionCommand();
        try {
            Set actionObjects = commands.get(actionCommand);
            for (Object actionObject : actionObjects) {
                ActionHandler c = (ActionHandler) actionObject;
//					preActionPerformed(c.getClass(), e);
                c.doAction(e);
//					postActionPerformed(c.getClass(), e);

            }
        } catch (NullPointerException er) {
            System.err.println(actionCommand + " not implemented");
            er.printStackTrace();
//			JMeterUtils.reportErrorToUser("Sorry, this feature (" + actionCommand + ") not yet implemented");
        }
    }

    public void actionPerformed(final ActionEvent e) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                performAction(e);
            }
        });
    }

}
